package repository

import (
	"awesomeProject/internal/model"
	"awesomeProject/pkg/errors"
	"context"

	"gorm.io/gorm"
)

type CommentRepository interface {
	Create(ctx context.Context, comment *model.Comment) error
	GetByID(ctx context.Context, id uint) (*model.Comment, error)
	Update(ctx context.Context, comment *model.Comment) error
	Delete(ctx context.Context, id uint) error
	ListByPost(ctx context.Context, postID uint, page, pageSize int) ([]*model.Comment, int64, error)
	ListByUser(ctx context.Context, userID uint, page, pageSize int) ([]*model.Comment, int64, error)
	GetReplies(ctx context.Context, parentID uint) ([]*model.Comment, error)
	GetCommentCount(ctx context.Context, postID uint) (int64, error)
}

// commentRepository 评论仓库接口实现
type commentRepository struct {
	db *gorm.DB
}

// NewCommentRepository 创建评论仓库实例
func NewCommentRepository(db *gorm.DB) CommentRepository {
	return &commentRepository{db: db}
}

// Create 创建评论
func (r *commentRepository) Create(ctx context.Context, comment *model.Comment) error {
	return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 验证帖子是否存在
		var post model.Post
		if err := tx.First(&post, comment.PostID).Error; err != nil {
			if err == gorm.ErrRecordNotFound {
				return errors.ErrPostNotFound
			}
			return err
		}
		
		// 如果是回复，验证父评论是否存在
		if comment.ParentID != nil {
			var parentComment model.Comment
			if err := tx.First(&parentComment, *comment.ParentID).Error; err != nil {
				if err == gorm.ErrRecordNotFound {
					return errors.ErrParentNotFound
				}
				return err
			}
		}
		
		return tx.Create(comment).Error
	})
}

// GetByID 根据id查询评论
func (r *commentRepository) GetByID(ctx context.Context, id uint) (*model.Comment, error) {
	var comment model.Comment
	result := r.db.WithContext(ctx).Preload("User").First(&comment, id)
	if result.Error != nil {
		return nil, result.Error
	}
	return &comment, nil
}

// Update 更新评论
func (r *commentRepository) Update(ctx context.Context, comment *model.Comment) error {
	return r.db.WithContext(ctx).Save(comment).Error
}

// Delete 删除评论
func (r *commentRepository) Delete(ctx context.Context, id uint) error {
	return r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
		// 先删除所有回复
		if err := tx.Where("parent_id = ?", id).Delete(&model.Comment{}).Error; err != nil {
			return err
		}
		// 再删除评论本身
		return tx.Delete(&model.Comment{}, id).Error
	})
}

// ListByPost 根据帖子id查询评论
func (r *commentRepository) ListByPost(ctx context.Context, postID uint, page, pageSize int) ([]*model.Comment, int64, error) {
	var comments []*model.Comment
	var count int64
	
	if err := r.db.WithContext(ctx).Model(&model.Comment{}).Where("post_id = ? AND parent_id IS NULL", postID).Count(&count).Error; err != nil {
		return nil, 0, err
	}
	
	offset := (page - 1) * pageSize
	result := r.db.WithContext(ctx).Where("post_id = ? AND parent_id IS NULL", postID).
		Preload("User").Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&comments)
	if result.Error != nil {
		return nil, 0, result.Error
	}
	
	return comments, count, nil
}

// ListByUser 根据用户id查询评论
func (r *commentRepository) ListByUser(ctx context.Context, userID uint, page, pageSize int) ([]*model.Comment, int64, error) {
	var comments []*model.Comment
	var count int64
	
	if err := r.db.WithContext(ctx).Model(&model.Comment{}).Where("user_id = ?", userID).Count(&count).Error; err != nil {
		return nil, 0, err
	}
	
	offset := (page - 1) * pageSize
	result := r.db.WithContext(ctx).Where("user_id = ?", userID).
		Preload("User").Offset(offset).Limit(pageSize).Order("created_at DESC").Find(&comments)
	if result.Error != nil {
		return nil, 0, result.Error
	}
	
	return comments, count, nil
}

// GetReplies 获取评论的回复
func (r *commentRepository) GetReplies(ctx context.Context, parentID uint) ([]*model.Comment, error) {
	var replies []*model.Comment
	result := r.db.WithContext(ctx).Where("parent_id = ?", parentID).
		Preload("User").Order("created_at ASC").Find(&replies)
	if result.Error != nil {
		return nil, result.Error
	}
	return replies, nil
}

// GetCommentCount 获取帖子下的评论数量
func (r *commentRepository) GetCommentCount(ctx context.Context, postID uint) (int64, error) {
	var count int64
	err := r.db.WithContext(ctx).Model(&model.Comment{}).Where("post_id = ?", postID).Count(&count).Error
	return count, err
}